package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.ResultCode;
import com.example.entity.Activity;
import com.example.entity.ActivityRecord;
import com.example.entity.Volunteer;
import com.example.exception.BusinessException;
import com.example.mapper.ActivityRecordMapper;
import com.example.service.ActivityRecordService;
import com.example.service.ActivityService;
import com.example.service.VolunteerService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ActivityRecordServiceImpl extends ServiceImpl<ActivityRecordMapper, ActivityRecord> implements ActivityRecordService {

    private final ActivityService activityService;
    private final VolunteerService volunteerService;

    @Override
    @Transactional
    public boolean signIn(Long activityId, Long volunteerId, String location) {
        // 检查活动是否存在且在进行中
        Activity activity = activityService.getActivityInfo(activityId);
        if (activity.getStatus() != 1) {
            throw new BusinessException("活动未开始或已结束");
        }

        // 检查志愿者是否存在
        Volunteer volunteer = volunteerService.getVolunteerInfo(volunteerId);
        
        // 检查是否已经签到
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getActivityId, activityId)
                .eq(ActivityRecord::getVolunteerId, volunteerId)
                .eq(ActivityRecord::getType, 0)
                .isNull(ActivityRecord::getSignOutTime);
        if (count(wrapper) > 0) {
            throw new BusinessException("已经签到，请勿重复签到");
        }

        // 创建签到记录
        ActivityRecord record = new ActivityRecord();
        record.setActivityId(activityId);
        record.setVolunteerId(volunteerId);
        record.setVolunteerName(volunteer.getName());
        record.setSignInTime(LocalDateTime.now());
        record.setLocation(location);
        record.setType(0);  // 正常签到
        record.setStatus(0);  // 待审核
        
        return save(record);
    }

    @Override
    @Transactional
    public boolean signOut(Long activityId, Long volunteerId) {
        // 查找未签退的记录
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getActivityId, activityId)
                .eq(ActivityRecord::getVolunteerId, volunteerId)
                .eq(ActivityRecord::getType, 0)
                .isNull(ActivityRecord::getSignOutTime);
        
        ActivityRecord record = getOne(wrapper);
        if (record == null) {
            throw new BusinessException("未找到签到记录");
        }

        // 更新签退时间和服务时长
        record.setSignOutTime(LocalDateTime.now());
        Duration duration = Duration.between(record.getSignInTime(), record.getSignOutTime());
        record.setServiceDuration(duration.toMinutes() / 60.0);  // 转换为小时
        
        return updateById(record);
    }

    @Override
    @Transactional
    public boolean addRecord(ActivityRecord record) {
        // 检查活动是否存在
        Activity activity = activityService.getActivityInfo(record.getActivityId());
        
        // 检查志愿者是否存在
        Volunteer volunteer = volunteerService.getVolunteerInfo(record.getVolunteerId());
        record.setVolunteerName(volunteer.getName());
        
        // 设置补录标记
        record.setType(1);  // 补录
        record.setStatus(0);  // 待审核
        
        // 计算服务时长
        if (record.getSignInTime() != null && record.getSignOutTime() != null) {
            Duration duration = Duration.between(record.getSignInTime(), record.getSignOutTime());
            record.setServiceDuration(duration.toMinutes() / 60.0);
        }
        
        return save(record);
    }

    @Override
    @Transactional
    public boolean reviewRecord(Long id, Integer status, String rejectReason, Long reviewerId) {
        // 检查记录是否存在
        ActivityRecord record = getById(id);
        if (record == null) {
            throw new BusinessException("签到记录不存在");
        }
        
        // 检查状态是否合法
        if (status < 0 || status > 2) {
            throw new BusinessException("状态值不合法");
        }
        
        // 更新审核信息
        record.setStatus(status);
        record.setRejectReason(rejectReason);
        record.setReviewerId(reviewerId);
        record.setReviewTime(LocalDateTime.now());
        
        return updateById(record);
    }

    @Override
    public Page<ActivityRecord> getRecordList(Integer pageNum, Integer pageSize, Long activityId, 
            Long volunteerId, Integer status, Integer type) {
        Page<ActivityRecord> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        
        // 构建查询条件
        if (activityId != null) {
            wrapper.eq(ActivityRecord::getActivityId, activityId);
        }
        if (volunteerId != null) {
            wrapper.eq(ActivityRecord::getVolunteerId, volunteerId);
        }
        if (status != null) {
            wrapper.eq(ActivityRecord::getStatus, status);
        }
        if (type != null) {
            wrapper.eq(ActivityRecord::getType, type);
        }
        
        wrapper.orderByDesc(ActivityRecord::getCreateTime);
        return page(page, wrapper);
    }

    @Override
    public ActivityRecord getRecordInfo(Long id) {
        ActivityRecord record = getById(id);
        if (record == null) {
            throw new BusinessException("签到记录不存在");
        }
        return record;
    }

    @Override
    @Transactional
    public boolean deleteRecord(Long id) {
        return removeById(id);
    }

    @Override
    @Transactional
    public boolean batchDeleteRecords(Long[] ids) {
        return removeByIds(Arrays.asList(ids));
    }

    @Override
    public Map<String, Object> getVolunteerServiceStats(Long volunteerId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 构建查询条件
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getVolunteerId, volunteerId)
               .eq(ActivityRecord::getStatus, 1);  // 只统计已审核的记录
        
        // 统计总服务时长
        double totalHours = list(wrapper).stream()
                .mapToDouble(ActivityRecord::getServiceDuration)
                .sum();
        
        // 统计参与活动次数
        long activityCount = list(wrapper).stream()
                .map(ActivityRecord::getActivityId)
                .distinct()
                .count();
        
        // 统计本月服务时长
        LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        wrapper.ge(ActivityRecord::getSignInTime, monthStart);
        double monthHours = list(wrapper).stream()
                .mapToDouble(ActivityRecord::getServiceDuration)
                .sum();
        
        stats.put("totalServiceHours", totalHours);
        stats.put("totalActivityCount", activityCount);
        stats.put("monthServiceHours", monthHours);
        
        return stats;
    }

    @Override
    public Map<String, Object> getActivityServiceStats(Long activityId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 构建查询条件
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getActivityId, activityId)
               .eq(ActivityRecord::getStatus, 1);  // 只统计已审核的记录
        
        // 获取活动信息
        Activity activity = activityService.getActivityInfo(activityId);
        
        // 统计参与人数
        long participantCount = list(wrapper).stream()
                .map(ActivityRecord::getVolunteerId)
                .distinct()
                .count();
        
        // 统计总服务时长
        double totalHours = list(wrapper).stream()
                .mapToDouble(ActivityRecord::getServiceDuration)
                .sum();
        
        // 计算出勤率
        double attendanceRate = participantCount * 100.0 / activity.getRecruitNumber();
        
        stats.put("participantCount", participantCount);
        stats.put("totalServiceHours", totalHours);
        stats.put("attendanceRate", attendanceRate);
        stats.put("recruitNumber", activity.getRecruitNumber());
        
        return stats;
    }

    @Override
    public Map<String, Object> getServiceStatsByDateRange(String startDate, String endDate) {
        Map<String, Object> stats = new HashMap<>();
        
        LocalDateTime start = LocalDateTime.parse(startDate + "T00:00:00");
        LocalDateTime end = LocalDateTime.parse(endDate + "T23:59:59");
        
        // 构建查询条件
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(ActivityRecord::getSignInTime, start)
               .le(ActivityRecord::getSignInTime, end)
               .eq(ActivityRecord::getStatus, 1);  // 只统计已审核的记录
        
        List<ActivityRecord> records = list(wrapper);
        
        // 统计服务总时长
        double totalHours = records.stream()
                .mapToDouble(ActivityRecord::getServiceDuration)
                .sum();
        
        // 统计参与人数
        long participantCount = records.stream()
                .map(ActivityRecord::getVolunteerId)
                .distinct()
                .count();
        
        // 统计活动数量
        long activityCount = records.stream()
                .map(ActivityRecord::getActivityId)
                .distinct()
                .count();
        
        stats.put("totalServiceHours", totalHours);
        stats.put("participantCount", participantCount);
        stats.put("activityCount", activityCount);
        
        return stats;
    }

    @Override
    public List<Map<String, Object>> getVolunteerRankingList(Integer limit) {
        // 构建查询条件
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getStatus, 1);  // 只统计已审核的记录
        
        // 获取所有记录
        List<ActivityRecord> records = list(wrapper);
        
        // 按志愿者分组并计算服务时长
        return records.stream()
                .collect(Collectors.groupingBy(
                    ActivityRecord::getVolunteerId,
                    Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> {
                            Map<String, Object> volunteerStats = new HashMap<>();
                            volunteerStats.put("volunteerId", list.get(0).getVolunteerId());
                            volunteerStats.put("volunteerName", list.get(0).getVolunteerName());
                            volunteerStats.put("serviceHours", list.stream()
                                    .mapToDouble(ActivityRecord::getServiceDuration)
                                    .sum());
                            volunteerStats.put("activityCount", list.stream()
                                    .map(ActivityRecord::getActivityId)
                                    .distinct()
                                    .count());
                            return volunteerStats;
                        }
                    )))
                .values()
                .stream()
                .sorted((a, b) -> Double.compare(
                    (Double) b.get("serviceHours"),
                    (Double) a.get("serviceHours")))
                .limit(limit)
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> getActivityParticipationAnalysis(Long activityId) {
        Map<String, Object> analysis = new HashMap<>();
        
        // 构建查询条件
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getActivityId, activityId);
        
        List<ActivityRecord> records = list(wrapper);
        
        // 统计各状态的记录数
        Map<Integer, Long> statusCount = records.stream()
                .collect(Collectors.groupingBy(
                    ActivityRecord::getStatus,
                    Collectors.counting()));
        
        // 统计签到时间分布
        Map<String, Long> timeDistribution = records.stream()
                .collect(Collectors.groupingBy(
                    record -> record.getSignInTime().format(DateTimeFormatter.ofPattern("HH:00")),
                    Collectors.counting()));
        
        // 统计平均服务时长
        double avgServiceHours = records.stream()
                .filter(r -> r.getServiceDuration() != null)
                .mapToDouble(ActivityRecord::getServiceDuration)
                .average()
                .orElse(0.0);
        
        analysis.put("statusDistribution", statusCount);
        analysis.put("timeDistribution", timeDistribution);
        analysis.put("averageServiceHours", avgServiceHours);
        
        return analysis;
    }

    @Override
    public List<Map<String, Object>> getServiceTypeDistribution() {
        // 获取所有已审核的记录
        LambdaQueryWrapper<ActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ActivityRecord::getStatus, 1);
        List<ActivityRecord> records = list(wrapper);
        
        // 获取关联的活动信息
        List<Activity> activities = activityService.listByIds(
                records.stream()
                        .map(ActivityRecord::getActivityId)
                        .collect(Collectors.toSet())
        );
        
        // 按服务类型分组统计
        Map<String, List<Activity>> typeGroups = activities.stream()
                .collect(Collectors.groupingBy(Activity::getServiceType));
        
        return typeGroups.entrySet().stream()
                .map(entry -> {
                    Map<String, Object> typeStats = new HashMap<>();
                    typeStats.put("serviceType", entry.getKey());
                    typeStats.put("activityCount", entry.getValue().size());
                    typeStats.put("participantCount", records.stream()
                            .filter(r -> entry.getValue().stream()
                                    .anyMatch(a -> a.getId().equals(r.getActivityId())))
                            .map(ActivityRecord::getVolunteerId)
                            .distinct()
                            .count());
                    return typeStats;
                })
                .collect(Collectors.toList());
    }
} 